﻿using Jellyfin.Plugin.JavMetadata.Dto;
using Jellyfin.Plugin.JavMetadata.Service;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Jellyfin.Plugin.JavMetadata.Site.Sod.Service
{
    public class SodHttpService : HttpService
    {
        private readonly ILogger<SodHttpService> _logger;
        private readonly IHttpClientFactory _http;

        // 首次请求需要年龄验证, 需要请求 https://ec.sod.co.jp/prime/_ontime.php 才能正常显示页面

        public SodHttpService(ILogger<SodHttpService> logger, IHttpClientFactory http) : base(logger, http)
        {
            _logger = logger;
            _http = http;
        }


        public override async Task<string> GetHtmlAsync(string url, CancellationToken cancellationToken)
        {
            //return base.GetHtmlAsync(url, cancellationToken);

            var request = new HttpRequestMessage(HttpMethod.Get, url);
            request.Headers.Add("Referer", "https://ec.sod.co.jp/");
            var response = await _http.CreateClient(NamedClient.Default).SendAsync(request);
            var content = await response.Content.ReadAsStringAsync();

            // 包含 18歳以上です / pkg_age 其中一个说明是年龄确认页
            if (content.Contains("18歳以上です"))
            {
                await _http.CreateClient(NamedClient.Default).GetAsync("https://ec.sod.co.jp/prime/_ontime.php");
                return await GetHtmlAsync(url, cancellationToken); 
            }

            return content; //await response.Content.ReadAsStringAsync();
        }


        public override async Task<HttpResponseMessage> GetResponseAsync(string url, CancellationToken cancellationToken)
        {
            //return base.GetResponseAsync(url, cancellationToken);

            var request = new HttpRequestMessage(HttpMethod.Get, url);
            request.Headers.Add("Referer", "https://ec.sod.co.jp/");
            var response = await _http.CreateClient(NamedClient.Default).SendAsync(request);
            var content = await response.Content.ReadAsStringAsync();

            // 包含 18歳以上です / pkg_age 其中一个说明是年龄确认页
            if (content.Contains("18歳以上です"))
            {
                await _http.CreateClient(NamedClient.Default).GetAsync("https://ec.sod.co.jp/prime/_ontime.php");
                return await GetResponseAsync(url, cancellationToken);
            }

            return response;
        }

        public override async Task<T> GetMovieAsync<T>(string id, CancellationToken cancellationToken)
        {
            // id 不能为空
            if (string.IsNullOrWhiteSpace(id))
            {
                _logger.LogError("id is null.");
                throw new ArgumentException("sid is empty when getting subject");
            }

            // 拼接 url
            var url = $"https://{Plugin.Instance.Configuration.Sod.Domain}/videos/?id={id}";

            // 确认
            //await ConfirmAsync();

            // 拉取 html
            var html = await GetHtmlAsync(url, cancellationToken);

            var item = new MovieItem();

            var fanart = await GetFanartAsync(html, cancellationToken);
            item.Avid = await GetAvidAsync(html, cancellationToken);
            item.Title = await GetTitleAsync(html, cancellationToken);
            item.Poster = fanart.Replace("_l", "_m");
            item.Fanart = fanart;
            item.ReleaseDate = GetReleaseDate(html);
            item.Duration = GetDuration(html);
            item.Directors = await GetDirectorsAsync(html, cancellationToken);
            item.Studios = await GetStudiosAsync(html, cancellationToken);
            item.Labels = await GetLabelsAsync(html, cancellationToken);
            item.Series = await GetSeriesAsync(html, cancellationToken);
            item.Genres = await GetGenresAsync(html, cancellationToken);
            item.Actresses = await GetActressesAsync(html, cancellationToken);
            item.Shotscreens = await GetScreenshotsAsync(html, cancellationToken);
            item.SourceUrl = url;
            return item as T;
        }

        public override async Task<MetadataResult<Movie>> GetMovieMetadataAsync(string id, CancellationToken cancellationToken)
        {
            var result = new MetadataResult<Movie>();

            // 如果 id 为空，则直接返回空结果
            if (string.IsNullOrWhiteSpace(id))
            {
                _logger.LogError("sid is empty when getting subject.");
                return result;
            }

            // 获取影片详情
            var item = await GetMovieAsync<MovieItem>(id, cancellationToken);

            // 设置 基础信息
            var movie = new Movie
            {
                Name = item.Title,
                OriginalTitle = $"{item.Avid} {item.Title}",
                SortName = item.Avid,
                ForcedSortName = item.Title,                
                Overview = item.Intro,
                HomePageUrl = $"https://{Plugin.Instance.Configuration.Sod.Domain}/videos/?id={id}"
            };

            // 如果 系列 不为空
            if (item.Series?.Count > 0)
            {
                // 设置合集名
                movie.CollectionName = item.Series?[0];
            }

            // 如果 发行日期 不为空
            if (item.ReleaseDate != null)
            {
                var releaseDate = item.ReleaseDate?.ToUniversalTime();

                // 设置 发行日期
                movie.PremiereDate = releaseDate;
                // 设置 年份
                movie.ProductionYear = releaseDate?.Year;
            }

            // 添加类别
            item.Genres.ForEach((item) =>
            {
                movie.AddGenre(item);
            });

            // 添加 工作室
            item.Studios.ForEach((studio) =>
            {
                movie.AddStudio(studio);
            });

            // 添加 发行商
            item.Labels.ForEach((label) =>
            {
                // 不存在时才添加
                if (!movie.Studios.Contains(label))
                {
                    movie.AddStudio(label);
                }
            });

            // 添加 导演
            (await TransPersonInfoAsync(item.Directors, PersonType.Director, cancellationToken))?.ForEach((item) =>
            {
                result.AddPerson(item);
            });

            // 添加 演员
            (await TransPersonInfoAsync(item.Actresses, PersonType.Actor, cancellationToken))?.ForEach((item) =>
            {
                result.AddPerson(item);
            });

            // 添加 编剧
            //await TransPersonInfoAsync(movie.Writers, PersonType.Writer, cancellationToken).ForEach(result.AddPerson);

            result.QueriedById = false;
            result.HasMetadata = true;
            result.Item = movie;

            return result;
        }

        public override async Task<IEnumerable<T>> SearchAsync<T>(string keyword, CancellationToken cancellationToken)
        {
            var results = new List<T>();

            // 拼接 url
            var url = $"https://{Plugin.Instance.Configuration.Sod.Domain}/videos/genre/?search_type=1&sodsearch={keyword}";

            // 确认
            //await ConfirmAsync();

            // 查询
            var html = await GetHtmlAsync(url, cancellationToken);
            // 匹配影片
            var matches = Regex.Matches(html, Plugin.Instance.Configuration.Sod.SearchResultPattern);

            foreach (Match match in matches)
            {
                if (match.Success)
                {
                    var item = new SearchResult { Id = match.Groups["avid"].Value.Trim() };
                    results.Add(item as T);
                }
            }
            // 返回 30 条记录
            return (IEnumerable<T>)results.Distinct().Take(30).ToList();
        }

        /// <summary>
        /// 获取识别码
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public async Task<string> GetAvidAsync(string html, CancellationToken cancellationToken)
        {
            return await Task.Run(() =>
            {
                var match = Regex.Match(html, Plugin.Instance.Configuration.Sod.AvidPattern);

                if (match.Success)
                {
                    var title = match.Groups["avid"].Value.Trim();
                    return title;
                }
                return string.Empty;
            }, cancellationToken);
        }

        /// <summary>
        /// 获取标题
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public async Task<string> GetTitleAsync(string html, CancellationToken cancellationToken)
        {
            return await Task.Run(() =>
            {
                var match = Regex.Match(html, Plugin.Instance.Configuration.Sod.TitlePattern);

                if (match.Success)
                {
                    var title = match.Groups["title"].Value.Trim();
                    return title;
                }
                return string.Empty;
            }, cancellationToken);
        }

        /// <summary>
        /// 获取大封面 URL
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public async Task<string> GetFanartAsync(string html, CancellationToken cancellationToken)
        {
            return await Task.Run(() =>
            {
                var match = Regex.Match(html, Plugin.Instance.Configuration.Sod.CoverPattern);

                if (match.Success)
                {
                    return match.Groups["fanart"].Value.Trim();
                }
                return string.Empty;
            }, cancellationToken);
        }

        /// <summary>
        /// 获取发行日期
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public DateTime? GetReleaseDate(string html)
        {
            var match = Regex.Match(html, Plugin.Instance.Configuration.Sod.ReleaseDatePattern);
            if (match.Success)
            {
                var m = Regex.Match(match.Groups["date"].Value.Trim(), @"^(?<year>\d*)年\s*(?<month>\d*)月\s*(?<day>\d*)日");
                if (m.Success)
                {
                    // 提取年月日转为日期对象
                    DateTime.TryParse($"{m.Groups["year"].Value}-{m.Groups["month"].Value}-{m.Groups["day"].Value}", out DateTime date);
                    return date;
                }
            }
            return null;
        }

        /// <summary>
        /// 获取时长
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public int GetDuration(string html)
        {
            var match = Regex.Match(html, Plugin.Instance.Configuration.Sod.DurationPattern);
            if (match.Success)
            {
                int.TryParse(match.Groups["duration"].Value.Trim(), out int duration);
                return duration;
            }

            return 0;
        }

        /// <summary>
        /// 获取导演列表
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public async Task<List<PersonModel>> GetDirectorsAsync(string html, CancellationToken cancellationToken)
        {
            var list = new List<PersonModel>();
            return await Task.Run(() =>
            {
                var match = Regex.Match(html, Plugin.Instance.Configuration.Sod.DirectorListPattern);
                if (match.Success)
                {

                    var items = Regex.Matches(match.Groups["directors"].Value.Trim(), Plugin.Instance.Configuration.Sod.DirectorPattern);
                    foreach (Match item in items)
                    {
                        if (item.Success)
                        {
                            list.Add(new PersonModel
                            {
                                Name = item.Groups["name"].Value.Trim(),
                                Alt = item.Groups["url"].Value.Trim()
                            });
                        }
                    }
                    items = null;
                }

                return list;
            }, cancellationToken);
        }

        /// <summary>
        /// 获取工作室列表
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public async Task<List<string>> GetStudiosAsync(string html, CancellationToken cancellationToken)
        {
            var list = new List<string>();
            return await Task.Run(() =>
            {
                var match = Regex.Match(html, Plugin.Instance.Configuration.Sod.StudioListPattern);
                if (match.Success)
                {
                    var items = Regex.Matches(match.Groups["studios"].Value.Trim(), Plugin.Instance.Configuration.Sod.StudioPattern);
                    foreach (Match item in items)
                    {
                        if (item.Success)
                        {
                            list.Add(item.Groups["name"].Value.Trim());
                        }
                    }
                }
                return list;
            }, cancellationToken);
        }

        /// <summary>
        /// 获取发行商
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public async Task<List<string>> GetLabelsAsync(string html, CancellationToken cancellationToken)
        {
            var list = new List<string>();
            return await Task.Run(() =>
            {
                var match = Regex.Match(html, Plugin.Instance.Configuration.Sod.LabelPattern);
                if (match.Success)
                {
                    list.Add(match.Groups["label"].Value.Trim());
                }
                return list;
            }, cancellationToken);
        }

        /// <summary>
        /// 获取系列列表
        /// </summary>
        /// <param name="html"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<List<string>> GetSeriesAsync(string html, CancellationToken cancellationToken)
        {
            var list = new List<string>();
            return await Task.Run(() =>
            {
                var match = Regex.Match(html, Plugin.Instance.Configuration.Sod.CollectionListPattern);
                if (match.Success)
                {
                    var items = Regex.Matches(match.Groups["series"].Value.Trim(), Plugin.Instance.Configuration.Sod.CollectionPattern);
                    foreach (Match item in items)
                    {
                        if (item.Success)
                        {
                            list.Add(item.Groups["name"].Value.Trim());
                        }
                    }
                }

                return list;
            }, cancellationToken);
        }

        /// <summary>
        /// 获取风格列表
        /// </summary>
        /// <param name="html"></param>
        /// <returns></returns>
        public async Task<List<string>> GetGenresAsync(string html, CancellationToken cancellationToken)
        {
            var list = new List<string>();
            return await Task.Run(() =>
            {
                var match = Regex.Match(html, Plugin.Instance.Configuration.Sod.GenreListPattern);
                if (match.Success)
                {
                    var items = Regex.Matches(match.Groups["genres"].Value, Plugin.Instance.Configuration.Sod.GenrePattern);
                    foreach (Match item in items)
                    {
                        if (item.Success)
                        {
                            list.Add(item.Groups["name"].Value.Trim());
                        }
                    }
                }

                return list;
            }, cancellationToken);
        }

        /// <summary>
        /// 获取演员列表
        /// </summary>
        /// <param name="html">html 内容</param>
        /// <returns></returns>
        public async Task<List<PersonModel>> GetActressesAsync(string html, CancellationToken cancellationToken)
        {
            var list = new List<PersonModel>();
            return await Task.Run(() =>
            {
                var match = Regex.Match(html, Plugin.Instance.Configuration.Sod.ActressListPattern);
                if (match.Success)
                {
                    var items = Regex.Matches(match.Groups["actresses"].Value, Plugin.Instance.Configuration.Sod.ActressPattern);
                    foreach (Match item in items)
                    {
                        if (item.Success)
                        {
                            list.Add(new PersonModel
                            {
                                Name = item.Groups["name"].Value.Trim()
                            });
                        }
                    }
                }

                return list;
            }, cancellationToken);
        }


        /// <summary>
        /// 获取预览图列表
        /// </summary>
        /// <param name="html"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<List<string>> GetScreenshotsAsync(string html, CancellationToken cancellationToken)
        {
            var list = new List<string>();
            return await Task.Run(() =>
            {
                var match = Regex.Match(html, Plugin.Instance.Configuration.Sod.ScreenshotListPattern); //sample-waterfall"">\s*(?<thumbnails>[\w\W]*?)\s*</div>\s*<div

                // 匹配到数据
                if (match.Success)
                {
                    // 匹配 预览图 列表
                    var matches = Regex.Matches(match.Groups["screenshots"].Value, Plugin.Instance.Configuration.Sod.ScreenshotPattern); //href="(?<url>.*?)"\stitle="(?<name>.*?)"

                    // 遍历列表
                    foreach (Match m in matches)
                    {
                        // 匹配成功
                        if (m.Success)
                        {
                            list.Add(m.Groups["url"].Value.Trim());
                        }
                    }
                }
                return list;
            }, cancellationToken);
        }


        /// <summary>
        /// 转换 Dto 到 人员列表
        /// </summary>
        /// <param name="people"></param>
        /// <param name="personType"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<List<PersonInfo>> TransPersonInfoAsync(List<PersonModel> people, string personType, CancellationToken cancellationToken)
        {
            return await Task.Run(() =>
            {
                var result = new List<PersonInfo>();

                foreach (var person in people)
                {
                    var photo = person.Avatars?.Photo;
                    var personInfo = new PersonInfo
                    {
                        Name = person.Name, // 姓名
                        Role = person.Name, // 饰演的角色
                        Type = personType,
                        ImageUrl = photo //photo.EndsWith("nowprint.gif") == true ? "" : photo // 如果没有照片，则不显示
                    };

                    personInfo.SetProviderId($"{Plugin.Instance?.Configuration.Sod.ProviderName} Id", person.Id);
                    result.Add(personInfo);
                }

                return result;

            }, cancellationToken);
        }

        /// <summary>
        /// 将 Dto 转为 Movie
        /// </summary>
        /// <param name="detail"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<Movie> TransMediaInfoAsync(MovieItem detail, CancellationToken cancellationToken)
        {
            return await Task.Run(() =>
            {
                // 设置 基础信息
                var movie = new Movie
                {
                    Name = detail.Title,
                    OriginalTitle = $"{detail.Avid} {detail.Title}",
                    SortName = detail.Avid,
                    ForcedSortName = detail.Avid,
                    Overview = detail.Intro,
                    HomePageUrl = detail.SourceUrl
                };

                // 如果 发行日期 不为空
                if (detail.ReleaseDate != null)
                {
                    var releaseDate = detail.ReleaseDate?.ToUniversalTime();

                    // 设置 发行日期
                    movie.PremiereDate = releaseDate;
                    // 设置 年份
                    movie.ProductionYear = releaseDate?.Year;
                }

                // 添加类别
                detail.Genres.ForEach((item) =>
                {
                    movie.AddGenre(item);
                });

                // 添加 工作室
                detail.Studios.ForEach((studio) =>
                {
                    movie.AddStudio(studio);
                });

                // 添加 发行商
                detail.Labels.ForEach((label) =>
                {
                    // 不存在时才添加
                    if (!movie.Studios.Contains(label))
                    {
                        movie.AddStudio(label);
                    }
                });

                return movie;

            }, cancellationToken);
        }
    }
}
